Hilo 阿里H5游戏引擎简介

作者:annyran    |    发表于:    |    次访问    |   
文章目录
  1. 1. Hilo 阿里H5游戏引擎简介
    1. 1.1. Hilo

Hilo 阿里H5游戏引擎简介

最近找了一些与动画相关的资料,希望以后WAP的H5活动可以做一些比较炫酷的动画。目前找到了3个可供选择的动画库,下面重点介绍一些第一个Hilo。

  • Hilo 阿里开源动画框架 (有API, 应该阿里的开发者会长期维护,就是例子不多,支持多种渲染方式支持Canvas,Webgl,Dom)

  • Agile 一个叫A-jie的人写的 (没有API,但是看源码也很容易上手,且例子多,不支持多种渲染方式,设计初衷就是为了不用Canvas)

  • Collie(Adobe出的一个动画框架,有很多例子,有api, 还没来得及使用)

下面简单介绍一下,各个库:

Hilo

Hilo,一套HTML5跨终端的互动游戏解决方案。Hilo支持了多届淘宝&天猫狂欢城等双十一大型和日常营销活动。内核极简,提供包括DOM,Canvas,Flash,WebGL等多种渲染方案,满足全终端和性能要求。支持多种模块范式的包装版本以及开放的扩展方式,方便接入和扩展。提供对2D物理,骨骼动画的内建和扩展支持。另外,Hilo提供丰富的周边工具及开发案例。目前,Hilo已经开源,并入到Hilo Team中。开源地址 https://github.com/hiloteam/Hilo (欢迎Star)

Hilo采用极简的内核。核心模块包括基础类工具(Class),事件系统(EventMixin),渲染(Render)和可视对象(View),如下图所示。

Hilo 结构图

Hilo 最大的特点在于它的多种渲染方式,它提供DOM,Canvas,Flash,WebGL等多种渲染方案,可以做到跨全端,高性能的要求,之前天猫双11的喵喵舞、双11互动城、红包雨都是用它实现的。在Hilo官网的例子里面有个flappybird 游戏实现的小案例,代码很少可以看下,感觉很赞。但是在实现一些想要的动画效果时,自己还是觉得Canvas动画比较难控制,因为你画的元素在element里面看不到。我用renderType为dom的方式写了个下面的小例子供大家上手参考:(可以先大致看一下Hilo 的API)

Codepen 查看地址

大致讲一下这个小例子用到的一些方法:

  • 重点提下Hilo的View类

    Hilo的可视对象的基础类是View类。View 在表现上就是一个个矩形,无论图片还是文字都可以使用一个最小的矩形包裹。在这些可视对象上做平移,旋转,缩放,透明处理等操作就可以实现普通动画的绝大部分。View实现了可视对象展示的基本问题。


类似地,根据不同View的其他展示特性,Hilo扩展出舞台Stage,位图Bitmap,画图Graphic,精灵动画Sprite等类型。

  • 补充几点,我个人觉得使用上不是特别方便的几点

    • 我们所有可视的元素基类都是View, 这个View的配置项里面有几个非常重要的与定位相关的信息。在dom渲染模式下我们的元素position都是absolute的,我们位置信息里的x,y 指的是transform里面的x与y. 配置信息里面有pivotX,pivotY指的是transform-origin的x与y。

    • pivotX与pivotY 的值不支持百分数,且默认并不在元素的中心点的位置,而是在(0,0)的位置,这也意味着我们设置元素的pivotX,pivotY 为50% 50% 时,需要去根据这个元素的宽度和高度进行计算。(对于上面提到的这点:Agile这个框架就方便很多)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
function main(){
var resources = [
{id:'car1', src:'images/car1.png'},
{id:'car2', src:'images/car2.png'},
{id:'tree1', src:'images/tree1.png'},
{id:'tree2', src:'images/tree2.png'},
{id:'wheel', src:'images/wheel.png'}
];
loadResources(resources, init);
}
function loadResources(resources, cb){
//使用Hilo的LoadQueue类去加载我们要使用的资源
queueRes = new Hilo.LoadQueue();
queueRes.add(resources);
queueRes.on('complete', cb);
queueRes.start();
}
function init(){
var gameContainer = document.getElementById("game-container"),
containerWidth = window.innerWidth,
containerHeight = window.innerHeight;
//init stage
//初始化我们的舞台容器,我们所有的View类元素都会放入这个容器
stage = new Hilo.Stage({
renderType:'dom',
container: gameContainer,
width: containerWidth,
height: containerHeight
});
//绘制road并将它添加到舞台容器
var road = new Hilo.View({
renderType:'dom',
width:containerWidth,
height:360,
background:'rgb(7,51,105)',
y:containerHeight - 360
}).addTo(stage);
//绘制car
//drawCar(type,carX, carHeight, containerHeight)
drawCar(1, 50, 144, containerHeight, 360);
drawCar(2, 350, 144, containerHeight, 360);
//绘制树
addTree(containerHeight, containerWidth, 360);
//就像上篇Canvas动画谈到的那样,我们所有的动画都是通过不断地计时去做一些操作
var ticker = new Hilo.Ticker(20);
ticker.addTick(stage);
ticker.addTick(Hilo.Tween);
ticker.start();
}
function addTree(containerHeight, containerWidth, roadHeight) {
for (var i = 0; i < 5; i++) {
var index = Math.round(Math.random() * 2),
fx,tx;
if(index == 0) index =2;
var tree = new Hilo.Bitmap({
//获取资源队列中的对应资源
image: queueRes.get('tree'+index).content
});
tree.x = Math.random()*containerWidth + tree.width/2;
tree.scaleX = tree.scaleY = Math.random()*.7+.3;
tree.y = containerHeight - roadHeight - (tree.height*tree.scaleY);
tree.addTo(stage);
interlude(tree);
function interlude(tree){
var fx = Math.random() * containerWidth + tree.width / 2;
var tx = -fx + Math.max(containerWidth * 2, containerWidth + tree.width / 2 + fx);
tree.scaleX = tree.scaleY = Math.random()*.7+.3;
tree.y = containerHeight - roadHeight - (tree.height*tree.scaleY);
Hilo.Tween.fromTo(
tree, {x: -fx}, {x: tx},
{duration: 3000, ease: Hilo.Ease.Linear.EaseNone, onComplete: function(){
interlude(tree);
}}
);
}
}
}
//绘制汽车
function drawCar(type,carX, carHeight, containerHeight, roadHeight){
//wheel图片的相关信息
var wheel = {
width: 53,height:53
};
//先绘制carContainer 作为car的容器,然后向carContainer里面添加carBody和carWheel
if(type == 1){
var carContainer = new Hilo.Container({
x: carX+100,
y: containerHeight - roadHeight - carHeight - 25
});
}else{
var carContainer = new Hilo.Container({
x: carX,
y: containerHeight - roadHeight - carHeight - 25
});
}
//绘制车身
var carBody = new Hilo.Bitmap({
image: queueRes.get('car'+type).content,
rect:[0,0,257,144]
});
//绘制wheel_左边
var wheel_l = new Hilo.Bitmap({
image: queueRes.get('wheel').content,
x: 30 + wheel.width/2,
y: carHeight,
pivotX: wheel.width/2,
pivotY: wheel.height/2
});
//绘制wheel_右边
var wheel_r = new Hilo.Bitmap({
image: queueRes.get('wheel').content,
x: 175+ wheel.width/2,
y: carHeight,
pivotX: wheel.width/2,
pivotY: wheel.height/2
});
//移动wheel_l
//Tween.to(target, toProps, params) Tween类型动画
Hilo.Tween.to(
wheel_l,
{
rotation: wheel_l.rotation - 360
},
{
duration:200,
loop:true,
reverse:false
}
);
Hilo.Tween.to(
wheel_r,
{
rotation: wheel_r.rotation - 360
},
{
duration:200,
loop:true,
reverse:false
}
);
//carBody的上下移动
Hilo.Tween.to(
carBody,
{
y:carBody.y + 6
},
{
duration: 600,
loop: true,
reverse: true
}
);
//CarContainer的上下移动
if(type == 1){
Hilo.Tween.to(
carContainer,
{
x: carContainer.x + 100
},
{
duration: 500,
loop:true,
reverse:true,
ease:Hilo.Ease.Linear.EaseNone
}
);
}else{
Hilo.Tween.to(
carContainer,
{
x: carContainer.x
},
{
delay: 200,
duration: 500,
loop:true,
reverse:true,
ease:Hilo.Ease.Linear.EaseNone
}
);
}
carContainer.addChild(carBody);
carContainer.addChild(wheel_l);
carContainer.addChild(wheel_r);
carContainer.addTo(stage);
}
分享到